/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.saber.certificacao.beansjsf.login;

import br.com.saber.certificacao.beansjsf.interfacebean.BeanJSFInterface;
import br.com.saber.certificacao.beansjsf.principal.AlunosLogadosManager;
import br.com.saber.certificacao.ejbs.stateless.interfaces.RolesBeanLocal;
import br.com.saber.certificacao.ejbs.stateless.interfaces.UsuarioBeanLocal;
import br.com.saber.certificacao.modelos.Usuario;
import br.com.saber.certificacao.utils.UtilMetodos;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 *
 * @author gbvbahia
 */
@ManagedBean(name = "loginManager")
@SessionScoped
public class LoginManager implements BeanJSFInterface {

    @EJB
    private RolesBeanLocal rolesBean;
    @EJB
    private UsuarioBeanLocal usuarioBean;
    
    @ManagedProperty("#{fluxoExibicaoLogin}")
    private FluxoExibicao fluxoExibicaoLogin;
    
    private Usuario usuario;
    public static final String SESSION_PROPRIETARIO = "usuario_logado";
    public static final String SESSION_NIVEL = "nivel";
    private static Map<String, Integer> mapProtector = new HashMap<String, Integer>();

    /** Creates a new instance of LoginManager */
    public LoginManager() {
    }

    @Override
    @PostConstruct
    public void init() {
        this.usuario = new Usuario();
        Logger.getLogger(LoginManager.class.getName()).log(Level.FINEST, "LoginManager @SessionScoped: PostConstruct (init()) chamado...{0}", this.toString());
    }

    @Override
    @PreDestroy
    public void end() {
        Logger.getLogger(LoginManager.class.getName()).log(Level.FINEST, "LoginManager @SessionScoped: PreDestroy (end()) chamado...");
    }

    //====================
    //Métodos de Negócio
    //====================
    public String logar() {
        Usuario comp = usuarioBean.buscarUsuarioLogin(usuario.getLogin());
        if (comp != null) {
            Logger.getLogger(LoginManager.class.getName()).log(Level.INFO, "Usuario: {0} Senha: {1} Crip: {2}", new Object[]{usuario.getLogin(), "******", this.usuarioBean.criptografarSenha(usuario.getSenha(), comp.getRoles())});
        }
        if (comp != null && comp.getSenha().equals(this.usuarioBean.criptografarSenha(usuario.getSenha(), comp.getRoles()))) {
            if (comp.isBloqueado()) {
                UtilMetodos.messageFactoringFull("loginBloqueado", FacesMessage.SEVERITY_WARN, FacesContext.getCurrentInstance());
                return null;
            }
            //UtilMetodos.messageFactoringFull("loginValido", FacesMessage.SEVERITY_INFO, FacesContext.getCurrentInstance());
            insereProprietarioSession(comp);
            setUsuario(comp);
            removerMapProtector();
            this.usuarioBean.incrementarAcesso(usuario);
            if (this.usuario.getAcessos() > 0){
                 return "prova.xhtml";
            }else{
                return "principal.xhtml";
            }
        } else {
            UtilMetodos.messageFactoringFull("loginInvalido", FacesMessage.SEVERITY_ERROR, FacesContext.getCurrentInstance());
            Logger.getLogger(LoginManager.class.getName()).log(Level.WARNING, "Tentativa de login sem sucesso, Usuario: {0}", usuario.getLogin());
            verificaTentativaInvalidaDeLogin();
            return null;
        }
    }

    /**
     * Caso alguém coloque um robô para tentar logar terá que esperar cada vez mais pelo retorno
     * da tentativa de login
     */
    private void verificaTentativaInvalidaDeLogin() {
        HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
        String ip = req.getRemoteAddr();
        int time = 1;
        if (mapProtector.containsKey(ip)) {
            time = mapProtector.get(ip) * 4;
            mapProtector.put(ip, mapProtector.get(ip) + 1);
        } else {
            mapProtector.put(ip, time);
        }
        try {
            Thread.sleep(time * 1000);
        } catch (InterruptedException ex) {
            Logger.getLogger(LoginManager.class.getName()).log(Level.SEVERE, "*** Thread Login: ***", ex);
        }
    }

    private void removerMapProtector() {
        HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
        String ip = req.getRemoteAddr();
        mapProtector.remove(ip);
    }

    private void insereProprietarioSession(Usuario usuario) {
        HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
        session.setAttribute(SESSION_PROPRIETARIO, usuario);
        session.setAttribute(SESSION_NIVEL, rolesBean.getMaxRole(usuario.getRoles()).getLevel());
        AlunosLogadosManager.addUser(usuario);
    }

    public String deslogar() {
        HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
        session.invalidate();
        return fluxoExibicaoLogin.exibirLogin();
    }

    //=========================
    //Getters AND Setters
    //=========================
    public Usuario getUsuario() {
        return usuario;
    }

    public void setUsuario(Usuario usuario) {
        this.usuario = usuario;
    }

    public FluxoExibicao getFluxoExibicaoLogin() {
        return fluxoExibicaoLogin;
    }

    public void setFluxoExibicaoLogin(FluxoExibicao fluxoExibicaoLogin) {
        this.fluxoExibicaoLogin = fluxoExibicaoLogin;
    }
}
